/*
 * @(#)SyslogEvent.java	1.0 Mar 8, 2008
 *
 *	The MIT License
 *
 *	Copyright (c) 2008 Malachi de AElfweald <malachid@gmail.com>
 *
 *	Permission is hereby granted, free of charge, to any person obtaining a copy
 *	of this software and associated documentation files (the "Software"), to deal
 *	in the Software without restriction, including without limitation the rights
 *	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *	copies of the Software, and to permit persons to whom the Software is
 *	furnished to do so, subject to the following conditions:
 *
 *	The above copyright notice and this permission notice shall be included in
 *	all copies or substantial portions of the Software.
 *
 *	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *	THE SOFTWARE.
 */
package org.eoti.net.syslog;

import org.eoti.net.SocketUtil;

import java.net.DatagramPacket;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/*
 * Parameters are as defined by http://www.ietf.org/internet-drafts/draft-ietf-syslog-syslog-09.txt
 * Syslog Format:
 *	&lt;PRI&gt; TIMESTAMP HOSTNAME TAG CONTENT
 * Example:
 * 	&lt;178&gt;Apr 15 10:55:13 malachid jconnection: unable to connect to the remote server 'rickv'
 * Where:
 * 	PRI = (facility * 8) + Severity
 *	TIMESTAMP = Mmm dd hh:mm:ss
 *	HOSTNAME = hostname or address
 *	TAG = unique identifier of facility
 *	CONTENT = Message to output
 */
public class SyslogEvent
{
	protected Facility facility = Facility.Kernel;
	protected Severity severity = Severity.Emergency;
	protected String host = SocketUtil.getLocalHost().getHostName();
	protected String appTag = "unknown";
	protected String message = "-empty message-";
	protected Date timestamp = new Date();
	protected static String toStringFMT = "<%d>%s %s %s: %s";
	protected static SimpleDateFormat sdf = new SimpleDateFormat("MMM dd hh:mm:ss");
	protected static Pattern pattern = Pattern.compile("\\<([\\d]+)\\>([\\w]+[\\s][\\d]+[\\s][\\d]+\\:[\\d]+\\:[\\d]+)[\\s]([^\\s]+)[\\s]([^\\s]+)[\\s](.*)");

	public SyslogEvent()
	{

	}

	public SyslogEvent(String toParse)
	throws Exception
	{
		parse(toParse);
	}

	public SyslogEvent(DatagramPacket packet)
	throws ParseException
	{
		int offset = packet.getOffset();
		int length = packet.getLength();
		byte[] data = packet.getData();
		String toParse = new String(data, offset, length);
		parse(toParse);
	}

	protected void parse(String toParse)
	throws ParseException
	{
		Matcher matcher = pattern.matcher(toParse);
		if(!matcher.find())
		{
			setMessage(toParse);
			return;
		}
		int groups = matcher.groupCount();
		if(groups < 5)
		{
			setMessage(toParse);
			return;
		}
		setPriority(Integer.parseInt(matcher.group(1)));
		setTimestamp(matcher.group(2));
		setHost(matcher.group(3));
		setApplicationTag(matcher.group(4));
		setMessage(matcher.group(5));
	}

	public void setFacility(Facility facility){this.facility = facility;}
	public Facility getFacility(){return facility;}

	public void setSeverity(Severity severity){this.severity = severity;}
	public Severity getSeverity(){return severity;}

	public void setHost(String host){this.host = host;}
	public String getHost(){return host;}

	public void setApplicationTag(String appTag){this.appTag = appTag;}
	public String getApplicationTag(){return appTag;}

	public void setMessage(String message){this.message = message;}
	public String getMessage(){return message;}

	public void setTimestamp(Date timestamp){this.timestamp = timestamp;}
	public Date getTimestamp(){return timestamp;}
	public void setTimestamp(String timestamp)
	throws ParseException
	{
		setTimestamp(sdf.parse(timestamp));
	}
	public String getTimestampAsString(){return sdf.format(timestamp);}

	public void setPriority(int priority)
	{
		int fac = priority / 8;
		int sev = priority - (fac * 8);
		setFacility(Facility.values()[fac]);
		setSeverity(Severity.values()[sev]);
	}

	public int getPriority()
	{
		return (facility.ordinal() * 8) + severity.ordinal();
	}

	public String toString()
	{
		String message = String.format(toStringFMT, getPriority(), getTimestampAsString(), getHost(), getApplicationTag(), getMessage());
		if(message.length() > 1024)
			message = message.substring(0, 1023);

		return message;
	}
}
